	 PAGE  84,132
	 .SALL

;	   FILE = ADVSYSI/ASM	LAST MODIFIED: 10/11/85

	 NAME	 ADVSYSI
	 TITLE	 ADVSYSI V1.4 - (C) 1984 BOB WITHERS & STEVE O'DEA

	 SUBTTL  ADVENTURE KERNEL SYSTEM INTERFACE MODULE
	 PAGE	 +

; VERSION 1.1 - 12/30/84
;	      CORRECTED ERRORS IN THE SCROLL DOWN ROUTINE (SCRDN)
;	      AND LOCATE LAST LINE OF OVERLAY ROUTINE (CALC_LAST)
;	      WHICH WERE PREVENTING THEM FROM WORKING PROPERLY.
; VERSION 1.2 - 09/29/85
;	      ADDED ENHANCEMENTS TO ALLOW MORE THAN 255 PICTURE
;	      OVERLAYS TO BE HANDLED BY APPENDING 0FFH (OV2) AS
;	      A PREFIX TO THE OVERLAY NUMBER.
;	      ROUTINES AFFECTED: SHOOBJ, SHOOVL
; VERSION 1.3 - 10/11/85
;	      ADDED F1 KEY AS A PANIC BUTTON TO DISPLAY A CLEAR
;	      TEXT SCREEN WITH A DOS PROMPT.  F2 KEY IS THEN USED
;	      TO RESUME THE GAME.
; VERSION 1.4 - 12/15/87
;	      Modified timer interrupt CHKANT to use INT 08H rather than
;	      INT 1CH to support TI S1100.
;

	 INCLUDE ADVEQU.ASM

	 INCLUDE ADVMACRO.ASM

ABS0	 SEGMENT AT 0000H

	 ORG   0070H
TIMER_INT DD   ?		  ;TIMER TICK INTERRUPT VECTOR

	 ORG   0410H
EQUIP_FLAG DW  ?		  ;EQUIPMENT INSTALLED FLAG

	 ORG   046CH
TIMER_LOW1 DB  ?
TIMER_LOW2 DB  ?		  ;LOW ORDER BYTE OF TIMER_LOW

ABS0	 ENDS

VIDEO	 SEGMENT AT 0B800H

	 ORG   0
GSCRN1@W LABEL WORD
GSCRN1	 DB    92/2*80 DUP(?)	  ;EVEN SCAN LINES GRAPHIC SCREEN
TSCRN1@W LABEL WORD
TSCRN1	 DB    108/2*80 DUP(?)	  ;EVEN SCAN LINES TEXT SCREEN
	 ORG   2000H
GSCRN2@W LABEL WORD
GSCRN2	 DB    92/2*80 DUP(?)	  ;ODD SCAN LINES GRAPHIC SCREEN
TSCRN2@W LABEL WORD
TSCRN2	 DB    108/2*80 DUP(?)	  ;ODD SCAN LINES TEXT SCREEN

VIDEO	 ENDS

DATA	 SEGMENT PUBLIC

	 EXTRN	 COLOR1:BYTE,	 COLOR2:BYTE,	 ANTTAB:BYTE
	 EXTRN	 ROWCOL:WORD,	 ROW:BYTE,	 COL:BYTE
	 EXTRN	 MOVOBJ:BYTE,	 ROOM:BYTE,	 ANTIMSW:BYTE
	 EXTRN	 SCROBJ:BYTE,	 SCRPOS:WORD,	 LINELEN:BYTE
	 EXTRN	 ADVNUM:BYTE,	 CURCHR:BYTE,	 KEYBUF:BYTE
	 EXTRN	 TXTTAB:BYTE,	 MSGLNS:BYTE,	 GPC_TAB:WORD
	 EXTRN	 MODE:BYTE,	 COUNT:BYTE,	 CUR_BYT1:BYTE
	 EXTRN	 CUR_BYT2:BYTE,  REFRCT:BYTE,	 CUR_BYTE@W:WORD
	 EXTRN	 NLNSCT:BYTE,	 MSGMOR:BYTE,	 LIT160:BYTE
	 EXTRN	 EIGHTY:BYTE,	 ROOMTB:BYTE,	 STARTVAR:BYTE
	 EXTRN	 RMTB_LEN:WORD,  GAMSAV:BYTE,	 SAVNO:BYTE
	 EXTRN	 RECSIZ:WORD,	 RANDOM:BYTE,	 CURR_REC:BYTE
	 EXTRN	 SAVEKEY1:BYTE,  SAVEKEY2:BYTE
	 EXTRN	 SCROB2:BYTE

SAVMSG1  DB    13,'Inser','t'+80H,'gam','e'+80H,'sav','e'+80h
	 DB    'dis','k'+80H,'i','n'+80H,'driv','e'+80H,'A'+80H,C$AND
	 DB    'ente','r'+80H,C$THE,'position:',13
	 DB    '(0-9,<ENTER>=Abort',')'+80H,0
SAVMSG2  DB    13,'N','o'+80H,'roo','m'+80H,'i','n'+80H
	 DB    'directory.',0
SAVMSG3  DB    13,'Dis','k'+80H,'full.',0
SAVMSG4  DB    13,'Save','d'+80H,'gam','e'+80H
	 DB    'no','t'+80H,'found.',0
SAVMSG5  DB    13,'Unexpecte','d'+80H,'rea','d'+80H
	 DB    'erro','r'+80H,'-'+80H,'Aborted.',0
SAVMSG6  DB    13,'Invali','d'+80H,'sav','e'+80H,'fil','e'+80H
	 DB    '-'+80H,'Aborted.',0
SAVERR	 DB    13,'Unexpecte','d'+80H,'dis','k'+80H
	 DB    'I/','O'+80H,'erro','r'+80H,'-'+80H
	 DB    'Aborted.',0

DOS_PROMPT DB  13,'A>$'

DTABUF	 DB    128 DUP(?)

SAVE_SCR DB    16384 DUP(?)
END_SCR  LABEL BYTE

DATA	 ENDS

CODE	 SEGMENT PUBLIC

	 ASSUME  CS:CODE,DS:DATA,ES:VIDEO

	 PUBLIC  CLS,	   CLSTXT,   SHOSCR,   SHOOBJ,	 SHOOVL
	 PUBLIC  DISPLY,   CHROUT,   GETLIN,   SOUND
	 PUBLIC  SCRLFT,   SCRRIT,   SCRUP,    SCRDN,	 REPCLR
	 PUBLIC  FLPCLR,   CHKANT,   BIT_EXPL, CLS_CLR,  LODGAM
	 PUBLIC  SAVGAM,   DSKERR,   CLR_CHAR

	 EXTRN	 PNTRM1:NEAR,	 PNTRM2:NEAR,	 DS_SAVE:WORD
	 EXTRN	 REPLY:NEAR
	 extrn	 OldInt08:dword

	 EXTRN	 ZPALETTE:BYTE,  ZVIDMODE:BYTE

	 DB    'ADVSYSI - V1.4  12/15/87'

;********************************************************************
;
;  CLS	  CLEAR ENTIRE GRAPHIC & TEXT SCREENS
;	  (ENTRY POINT "CLS_CLR" ALLOWS DEFAULT COLOR IN "AX")
;
;	  INPUT:  NONE
;	  OUTPUT: NONE
;
;********************************************************************

CLS	 PROC
	 PUSH  AX		  ;SAVE REGISTERS
	 PUSH  BX
	 PUSH  CX
	 MOV   AX,WHITE@W	  ;SETUP ALL WHITE PIXELS
CLS_A:
	 MOV   BX,0		  ;DISPL INTO SCREEN
	 MOV   CX,200/2*40	  ;# SCANLINES / 2 * BYTES PER SCANLINE
CLS_B:
	 MOV   GSCRN1@W [BX],AX   ;CLEAR EVEN SCAN LINES
	 MOV   GSCRN2@W [BX],AX   ;CLEAR ODD SCAN LINES
	 ADD   BX,2		  ;INC SCREEN DISPL BY WORD SIZE
	 LOOP  CLS_B		  ;LOOP TILL DONE
	 POP   CX		  ;RESTORE REGISTERS
	 POP   BX
	 POP   AX
	 RET
CLS_CLR:
	 PUSH  AX		  ;SAVE REGISTERS
	 PUSH  BX
	 PUSH  CX
	 JMP   SHORT CLS_A
CLS	 ENDP

;********************************************************************
;
;  CLSTXT - CLEAR TEXT AREA OF THE SCREEN
;
;	  INPUT:  NONE
;	  OUTPUT: NONE
;
;********************************************************************

CLSTXT	 PROC
	 PUSH  AX		  ;SAVE REGISTERS
	 PUSH  BX
	 PUSH  CX
	 MOV   AX,WHITE@W	  ;SETUP ALL WHITE PIXELS
	 MOV   BX,0		  ;DISPL INTO SCREEN
	 MOV   CX,108/2*40	  ;# SCANLINES / 2 * BYTES PER SCANLINE
CLSTXT_A:
	 MOV   TSCRN1@W [BX],AX   ;CLEAR EVEN SCAN LINES
	 MOV   TSCRN2@W [BX],AX   ;CLEAR ODD SCAN LINES
	 ADD   BX,2		  ;INC SCREEN DISPL BY WORD SIZE
	 LOOP  CLSTXT_A 	  ;LOOP TILL DONE
	 MOV   COL,1
	 MOV   ROW,12
	 SETCUR
	 POP   CX		  ;RESTORE REGISTERS
	 POP   BX
	 POP   AX
	 RET
CLSTXT	 ENDP

;********************************************************************
;
;  SHOSCR - DISPLAY BACKGROUND SCREEN ON VIDEO
;
;	    INPUT:  SI = POINTER TO COMPRESSED SCREEN DATA
;	    OUTPUT: NONE
;
;********************************************************************

SHOSCR	 PROC
	 PUSH  AX		  ;SAVE REGISTERS
	 PUSH  DI
	 MOV   DI,88		  ;OFFSET FOR 1ST SCREEN LINE
	 MOV   AL,0		  ;1ST SCREEN LINE IS EVEN SCANLINE
	 CALL  DISPOVL		  ;DISPLAY THE SCREEN
	 POP   DI		  ;RESTORE REGISTERS
	 POP   AX
	 RET
SHOSCR	 ENDP

;********************************************************************
;
;  SHOOBJ - DISPLAY GRAPHIC OVERLAYS ON SCREEN
;
;********************************************************************

SHOOBJ	 PROC
	 PUSH  AX
	 PUSH  BX
	 PUSH  DI
	 PUSH  SI
	 CALL  PNTRM2		  ;PROCESS PERM OVERLAYS
	 INC   BX
SHOOBJ_A:
	 MOV   AL,[BX]
	 INC   BX
	 CMP   AL,0
	 JE    SHOOBJ_B
	 CMP   AL,OV2		  ;HANDLE 2ND 254 OVERLAY NUMBERS
	 JNE   SHOOBJ_M
	 MOV   AH,[BX]
	 INC   BX
SHOOBJ_M:
	 CALL  SHOOVL
	 JMP   SHORT SHOOBJ_A
SHOOBJ_B:
	 CALL  PNTRM1		  ;PROCESS MOVABLE OVERLAYS
SHOOBJ_C:
	 MOV   AL,[BX]
	 INC   BX
	 CMP   AL,0
	 JE    SHOOBJ_J
	 JS    SHOOBJ_C
	 MOV   SI,OFFSET MOVOBJ
SHOOBJ_D:
	 TEST  BYTE PTR [SI],0FFH
	 JE    SHOOBJ_C
	 INC   SI
	 CMP   AL,[SI-1]
	 JNE   SHOOBJ_H
	 MOV   DI,SI
SHOOBJ_N:
	 INC   SI
	 TEST  BYTE PTR [SI-1],0FFH
	 JNZ   SHOOBJ_N
SHOOBJ_E:
	 MOV   AH,[SI]
	 INC   SI
	 CMP   AH,0
	 JE    SHOOBJ_D
	 CMP   AH,ROOM
	 JNE   SHOOBJ_E
SHOOBJ_F:
	 MOV   AL,[DI]
	 INC   DI
	 CMP   AL,0
	 JE    SHOOBJ_C
	 CMP   AL,OV2
	 JNE   SHOOBJ_O
	 MOV   AH,[DI]
	 INC   DI
SHOOBJ_O:
	 CALL  SHOOVL
	 JMP   SHORT SHOOBJ_F
SHOOBJ_H:
	 INC   SI
	 TEST  BYTE PTR [SI-1],0FFH
	 JNZ   SHOOBJ_H
SHOOBJ_I:
	 INC   SI
	 TEST  BYTE PTR [SI-1],0FFH
	 JNE   SHOOBJ_I
	 JMP   SHORT SHOOBJ_D
SHOOBJ_J:
	 POP   SI
	 POP   DI
	 POP   BX
	 POP   AX
	 RET
SHOOBJ	 ENDP

;********************************************************************
;
;  SHOOVL - CALCULATE OVERLAY TABLE ENTRY FOR AN OVERLAY AND
;	    DISPLAY THE OVERLAY ON THE VIDEO SCREEN
;
;	    INPUT:  AL = OVERLAY NUMBER
;		    AH = OVERLAY NUMBER IF AL = 0FFH
;	    OUTPUT: NONE
;
;********************************************************************

SHOOVL	 PROC
	 PUSH  AX		  ;SAVE REGISTERS
	 PUSH  BX
	 PUSH  SI
	 PUSH  DI
	 CMP   AL,OV2		  ;2ND OVERLAY TABLE?
	 JNE   SHOOVL_B 	  ;NO
	 MOV   AL,AH
	 MOV   BX,OFFSET SCROB2   ;OVERLAY TABLE #2 OFFSET ADDR
	 JMP   SHORT SHOOVL_C
SHOOVL_B:
	 MOV   BX,OFFSET SCROBJ   ;OVERLAY TABLE OFFSET ADDR
SHOOVL_C:
	 DEC   AL		  ;CALC RELATIVE OVERLAY NUMBER
	 SUB   AH,AH		  ;REL OVERLAY # * LEN OF TABLE ENTRY
	 SHL   AX,1
	 SHL   AX,1
	 ADD   BX,AX		  ;CALC ADDR OF TABLE ENTRY
	 MOV   SI,[BX]		  ;POINTER TO COMPRESSED OVERLAY
	 MOV   DI,[BX+2]	  ;VIDEO SCREEN OFFSET
	 SUB   AL,AL		  ;ASSUME EVEN SCAN LINE START
	 CMP   DI,2000H 	  ;IS IT EVEN OR ODD?
	 JB    SHOOVL_A 	  ;IT IS EVEN, CONTINUE ON
	 SUB   DI,2000H 	  ;IT IS ODD, MAKE ADJUSTMENTS
	 INC   AL
SHOOVL_A:
	 CALL  DISPOVL		  ;DISPLAY THE OVERLAY
	 POP   DI		  ;RESTORE REGISTERS
	 POP   SI
	 POP   BX
	 POP   AX
	 RET
SHOOVL	 ENDP

;********************************************************************
;
;  DISPOVL - DISPLAY OVERLAY ON VIDEO SCREEN
;
;	    INPUT:  SI = POINTER TO THE COMPRESSED OVERLAY DATA
;		    DI = SCREEN OFFSET OF OVERLAY UPPER LEFT CORNER
;		    AL = EVEN/ODD VIDEO SCAN LINE INDICATOR
;			 IF = 0 START IS ON EVEN SCAN LINE
;			 IF = 1 START IS ON ODD SCAN LINE
;	    OUTPUT: NONE
;
;********************************************************************

DISPOVL  PROC
	 PUSH  AX		  ;SAVE REGISTERS
	 PUSH  BX
	 PUSH  CX
	 PUSH  SI
	 PUSH  DI
	 MOV   MODE,0		  ;INITIALIZE THE MODE SWITCH
	 MOV   SCRPOS,DI	  ;SAVE START SCREEN OFFSET
	 MOV   AH,[SI]		  ;GET LINE LENGTH OF THE OVERLAY
	 MOV   LINELEN,AH
	 INC   SI		  ;BUMP OVERLAY POINTER
	 CMP   AL,0		  ;IS IT ON EVEN SCAN LINE?
	 JNZ   DISPOVL_C	  ;  NO:PROCESS ODD SCAN LINE FIRST
DISPOVL_A:
	 MOV   CL,LINELEN	  ;GET LINE LENGTH OF THE OVERLAY
	 MOV   DI,SCRPOS	  ;CURRENT SCREEN OFFSET
DISPOVL_B:
	 CALL  OBJBYT		  ;GET NEXT OVERLAY DATA BYTE
	 JNZ   DISPOVL_E	  ;IF END OF OVERLAY DATA
	 SUB   AH,AH
	 SHL   AX,1
	 MOV   BX,AX
	 MOV   AX,GPC_TAB [BX]
	 MOV   GSCRN1@W [DI],AX   ;MOVE THE PIXELS TO SCREEN
	 ADD   DI,2		  ;INCREMENT SCREEN POINTER
	 DEC   CL		  ;DECREMENT LINE LENGTH COUNT
	 JNZ   DISPOVL_B	  ;LOOP THRU CURRENT SCAN LINE
DISPOVL_C:
	 MOV   CL,LINELEN	  ;GET LINE LENGTH OF THE OVERLAY
	 MOV   DI,SCRPOS	  ;CURRENT SCREEN OFFSET
DISPOVL_D:
	 CALL  OBJBYT		  ;GET NEXT OVERLAY DATA BYTE
	 JNZ   DISPOVL_E	  ;IF END OF OVERLAY DATA
	 SUB   AH,AH
	 SHL   AX,1
	 MOV   BX,AX
	 MOV   AX,GPC_TAB [BX]
	 MOV   GSCRN2@W [DI],AX   ;MOVE THE PIXELS TO SCREEN
	 ADD   DI,2		  ;INCREMENT SCREEN POINTER
	 DEC   CL		  ;DECREMENT LINE LENGTH COUNT
	 JNZ   DISPOVL_D	  ;LOOP THRU CURRENT SCAN LINE
	 MOV   DI,SCRPOS	  ;UPDATE SCREEN OFFSET TO NEXT LINE
	 ADD   DI,80
	 MOV   SCRPOS,DI
	 JMP   SHORT DISPOVL_A	  ;GO PROCESS EVEN SCAN LINE
DISPOVL_E:
	 POP   DI		  ;RESTORE REGISTERS & EXIT
	 POP   SI
	 POP   CX
	 POP   BX
	 POP   AX
	 RET
DISPOVL  ENDP

;********************************************************************
;
;  BIT_EXPL - EXPLODE A COLOR BYTE (4 PIXELS) INTO A COLOR WORD
;	      (8 PIXELS) BY DOUBLING EACH OF THE PIXELS
;
;	    INPUT:  AL = COLOR BYTE (4 PIXELS)
;	    OUTPUT: AX = COLOR WORD (8 PIXELS)
;
;********************************************************************

BIT_EXPL PROC
	 PUSH  BX		  ;SAVE REGISTERS
	 PUSH  CX
	 MOV   CH,4		  ;NUMBER OF PIXELS IN BYTE
	 MOV   CL,2		  ;NUMBER OF BITS IN A PIXEL
	 MOV   BL,AL		  ;GET THE COLOR BYTE
BIT_EXPL_A:
	 ROL   BL,CL		  ;GET NEXT PIXEL
	 MOV   BH,BL		  ;ISOLATE THE NEXT PIXEL
	 AND   BH,03H
	 SHL   AX,CL		  ;INSERT THE PIXEL TO OUTPUT
	 OR    AL,BH
	 SHL   AX,CL		  ;INSERT IT AGAIN
	 OR    AL,BH
	 DEC   CH		  ;DECREMENT # OF PIXELS TO PROCESS
	 JNZ   BIT_EXPL_A	  ;LOOP TILL DONE
	 XCHG  AH,AL		  ;SWITCH EM FOR INTEL
	 POP   CX		  ;RESTORE REGISTERS
	 POP   BX
	 RET
BIT_EXPL ENDP

;********************************************************************
;
;  OBJBYT - PROCESS COMPRESSED OVERLAY DATA AND RETURN THE NEXT
;	    DATA BYTE EACH TIME CALLED
;
;	    INPUT:  NONE (INITIALIZE "MODE" TO ZERO BEFORE 1ST CALL)
;	    OUTPUT: AL = NEXT BYTE OF OVERLAY DATA
;		    AH = STATUS OF REQUEST
;			 IF = 0 THEN DATA BYTE RETURNED
;			 IF = 1 THEN NO MORE DATA FOR OVERLAY
;
;********************************************************************

OBJBYT	 PROC
	 PUSH  BX		  ;SAVE REGISTERS
	 MOV   AL,MODE		  ;GET CURRENT ROUTINE MODE
	 CMP   AL,0		  ;START OOF NEW REPEAT BLOCK?
	 JZ    OBJBYT_E 	  ;  YES:PROCESS THE BLOCK
	 CMP   AL,1		  ;CURRENTLY PROCESSING REPEAT BLOCK?
	 JZ    OBJBYT_D 	  ;  YES:RETURN NEXT CHARACTER
	 CMP   AL,3		  ;PROCESSING SPECIAL 6 BYTE REPEAT?
	 JZ    OBJBYT_I 	  ;  YES:RETURN THE NEXT CHARACTER
	 MOV   AH,COUNT 	  ;PROCESS NON-REPEAT BLOCK
OBJBYT_A:
	 MOV   AL,[SI]		  ;GET NEXT DATA BYTE
	 INC   SI
OBJBYT_B:
	 DEC   AH		  ;REDUCE COUNT VALUE BY 1
	 JNZ   OBJBYT_C 	  ;IF NOT AT END OF COUNT VALUE
	 MOV   MODE,0		  ;RESET MODE FOR NEW BLOCK
OBJBYT_C:
	 MOV   COUNT,AH 	  ;SAVE NEW COUNT VALUE
	 POP   BX
	 SUB   AH,AH
	 RET
OBJBYT_D:
	 MOV   AH,COUNT 	  ;PROCESS NORMAL REPEAT BLOCK
	 MOV   AL,CUR_BYT1
	 JMP   SHORT OBJBYT_B
OBJBYT_E:
	 MOV   AL,[SI]		 ;SETUP FOR NEW REPEAT BLOCK
	 INC   SI
	 CMP   AL,0		 ;IS IT A REPEAT BLOCK?
	 JZ    OBJBYT_F 	 ;   YES:CONTINUE PROCESS
	 CMP   AL,0FFH		 ;IS IT END OF DATA?
	 JZ    OBJBYT_G 	 ;   YES:SET RETURN CODE
	 MOV   AH,AL		 ;   NO:SETUP AS NON-REPEAT BLOCK
	 MOV   MODE,2
	 JMP   SHORT OBJBYT_A
OBJBYT_F:
	 MOV   AH,[SI]		 ;CONTINUE SET-UP ON REPEAT BLOCK
	 INC   SI
	 CMP   AH,0		 ;IS IT SIX BYTE REPEAT BLOCK?
	 JZ    OBJBYT_H 	 ;   YES:PROCESS IT
	 MOV   MODE,1		 ;   NO:SET-UP FOR NORMAL REPEAT
	 MOV   AL,[SI]
	 INC   SI
	 MOV   CUR_BYT1,AL
	 JMP   SHORT OBJBYT_B
OBJBYT_G:
	 POP   BX		  ;   WITH END OF DATA SET
	 SUB   AH,AH
	 INC   AH
	 RET
OBJBYT_H:
	 MOV   MODE,3		 ;SET-UP FOR SIX BYTE REPEAT BLOCK
	 MOV   AL,[SI]
	 MOV   COUNT,AL
	 MOV   REFRCT,AL
	 INC   SI
	 MOV   AL,[SI]
	 MOV   NLNSCT,AL
	 INC   SI
	 MOV   AX,[SI]
	 ADD   SI,2
	 MOV   CUR_BYTE@W,AX
OBJBYT_I:
	 MOV   AL,CUR_BYT1	 ;PROCESS SIX BYTE REPEAT BLOCK
	 MOV   AH,COUNT
	 DEC   AH
	 JNZ   OBJBYT_C
	 PUSH  AX
	 MOV   AX,CUR_BYTE@W
	 XCHG  AH,AL
	 MOV   CUR_BYTE@W,AX
	 POP   AX
	 MOV   AH,REFRCT
	 DEC   NLNSCT
	 LBNE  OBJBYT_C
	 MOV   MODE,0
	 JMP   OBJBYT_C
OBJBYT	 ENDP

;********************************************************************
;
;  DISPLY - DISPLAY TEXT STRING ON VIDEO AT CURRENT ROW/COL AND
;	    PROVIDE FOR WORD WRAP
;
;	    INPUT:  BX = POINTER TO TEXT STRING (TERMINATED BY 00H)
;	    OUTPUT: NONE
;
;********************************************************************

DISPLY	 PROC
	 PUSH  AX
	 PUSH  BX
	 PUSH  DI
DISPLY_A:
	 MOV   DI,BX		  ;MOVE PNTR TO WORK REG
	 MOV   AH,0		  ;INIT COUNT TO END OF WORD
DISPLY_B:
	 INC   AH		  ;COUNT LENGTH OF CURRENT WORD
	 INC   DI
	 MOV   AL,[DI-1]
	 CMP   AL,0		  ;END OF STRING OR WORD?
	 JLE   DISPLY_D 	  ;  YES
	 CMP   AL,13		  ;IS CURRENT CHAR A C/R?
	 JE    DISPLY_D 	  ;  YES
	 CMP   AL,' '             ;IS CURRENT CHAR A SPACE?
	 JE    DISPLY_D 	  ;  YES
	 JMP   DISPLY_B 	  ;LOOP TILL END OF WORD
DISPLY_D:
	 MOV   AL,MAXLINE	  ;MAX DISPLAY LINE LEN
	 SUB   AL,COL		  ;SUBTRACT OUT CURRENT CURSOR POS
	 CMP   AH,AL		  ;ROOM ON THIS LINE FOOR WORD?
	 JLE   DISPLY_E 	  ;  YES:PLENTY OF ROOM
	 MOV   AL,13		  ;  NO:GO TO NEXT LINE
	 CALL  CHROUT
DISPLY_E:
	 MOV   AL,[BX]		  ;GET NEXT TEXT CHAR
	 INC   BX
	 CMP   AL,0
	 JE    DISPLY_H 	  ;IF END OF STRING
	 JG    DISPLY_G 	  ;IF NORMAL DISPLAY CHAR
	 CMP   AL,9FH		  ;COMPRESSED PHRASE CHAR?
	 JA    DISPLY_F 	  ;  NO:NORMAL CHAR WITH SPACE AFTER
	 CALL  TXTOUT		  ;PROCESS COMPRESSED PHRASE
	 JMP   DISPLY_A 	  ;PROCESS NEXT CHAR
DISPLY_F:
	 AND   AL,7FH		  ;REMOVE HI-ORDER BIT
	 CALL  CHROUT		  ;DISPLAY THE CHAR
	 MOV   AL,' '             ;DISPLAY SPACE AFTER CHAR
DISPLY_G:
	 CALL  CHROUT
	 JMP   DISPLY_A
DISPLY_H:
	 POP   DI
	 POP   BX
	 POP   AX
	 RET
DISPLY	 ENDP

;********************************************************************
;
;  TXTOUT - DISPLAY COMPRESSED PHRASE WITH POSSIBLE COMPRESSED
;	    PHRASES IMBEDDED WITHIN IT
;
;	    INPUT:  AL = COMPRESSED PHRASE NUMBER + 80H
;	    OUTPUT: NONE
;
;********************************************************************

TXTOUT	 PROC
	 PUSH  AX
	 PUSH  BX
	 PUSH  DI
	 MOV   BX,OFFSET TXTTAB   ;ADDR OF PHRASE TABLE
	 AND   AL,7FH		  ;HI-ORDER BIT OFF PHRASE NUMBER
	 JZ    TXTOUT_B 	  ;IF 1ST TABLE ENTRY
TXTOUT_A:
	 INC   BX		  ;LOOK FOR END OF PHRASE
	 TEST  BYTE PTR [BX-1],0FFH
	 JNZ   TXTOUT_A
	 DEC   AL
	 JNZ   TXTOUT_A
TXTOUT_B:
	 MOV   DI,BX		  ;SEE IF WORD WILL FIT ON CURR LINE
	 MOV   AH,0
TXTOUT_C:
	 INC   AH
	 INC   DI
	 MOV   AL,[DI-1]
	 CMP   AL,0
	 JLE   TXTOUT_E
	 CMP   AL,13
	 JE    TXTOUT_E
	 CMP   AL,' '
	 JE    TXTOUT_E
	 JMP   TXTOUT_C
TXTOUT_E:
	 MOV   AL,MAXLINE
	 SUB   AL,COL
	 CMP   AH,AL
	 JLE   TXTOUT_F 	  ;IF ROOM ON CURRENT LINE
	 MOV   AL,13		  ;IF NEW LINE NEEDED
	 CALL  CHROUT
TXTOUT_F:
	 INC   BX		  ;GET NEXT XHAR OF PHRASE
	 MOV   AL,[BX-1]
	 CMP   AL,0
	 JE    TXTOUT_I 	  ;IF END OF PHRASE
	 JG    TXTOUT_H 	  ;IF NORMAL DISPLAY CHAR
	 CMP   AL,9FH		  ;IS IT A COMPRESSED PHRASE?
	 JA    TXTOUT_G 	  ;  NO:NORMAL CHAR WITH SPACE AFTER
	 CALL  TXTOUT		  ;RECURSIVE CALL FOR COMPRESSED PHRASE
	 JMP   TXTOUT_B
TXTOUT_G:
	 AND   AL,7FH
	 CALL  CHROUT
	 MOV   AL,' '
TXTOUT_H:
	 CALL  CHROUT
	 JMP   TXTOUT_B
TXTOUT_I:
	 POP   DI
	 POP   BX
	 POP   AX
	 RET
TXTOUT	 ENDP

;********************************************************************
;
;  CHROUT - DISPLAY A SINGLE CHARACTER ON THE VIDEO SCREEN AT THE
;	    CURRENT ROW/COL
;
;	    INPUT:  AL = CHAR TO DISPLAY
;	    OUTPUT: NONE
;
;********************************************************************

CHROUT	 PROC
	 PUSH  AX
	 PUSH  DX
	 CMP   ROW,24		  ;PAST END OF SCREEN?
	 JL    CHROUT_A 	  ;  NO:CONTINUE ON
	 CALL  SCROLL		  ;  YES:SCROLL TEXT SCREEN
CHROUT_A:
	 SETCUR
	 CMP   AL,0DH		  ;IS IT A C/R?
	 JNZ   CHROUT_B 	  ;  NO
	 INC   MSGLNS
	 INC   ROW
	 MOV   COL,1
	 JMP   SHORT CHROUT_I
CHROUT_B:
	 CMP   AL,0CH		  ;IS IT CLEAR SCREEN?
	 JNE   CHROUT_C 	  ;  NO:CONTINUE ON
	 CALL  CLSTXT		  ;  YES:CLEAR TEXT SCREEN
	 JMP   SHORT CHROUT_I
CHROUT_C:
	 CMP   AL,08H		  ;BACKSPACE?
	 JNE   CHROUT_F 	  ;  NO
	 CALL  CLR_CHAR
	 CMP   ROWCOL,0 	  ;TOP OF SCREEN?
	 JE    CHROUT_I 	  ;  YES:IGNORE BACKSPACE
	 DEC   COL
	 JNZ   CHROUT_I
	 MOV   COL,MAXLINE
	 DEC   ROW
	 JMP   SHORT CHROUT_I
CHROUT_F:
	 CMP   AL,' '             ;LESS THAN SPACE?
	 JB    CHROUT_I 	  ;  YES:IGNORE
	 CMP   AL,07AH		  ;GREATER THAN LOWER CASE "Z"?
	 JA    CHROUT_I 	  ;  YES:IGNORE
	 DISABLE
	 DISCHR AL
	 ENABLE
	 INC   COL
	 CMP   COL,MAXLINE+1
	 JB    CHROUT_I
	 MOV   COL,1
	 INC   ROW
	 INC   MSGLNS
CHROUT_I:
	 POP   DX
	 POP   AX
	 RET
CHROUT_J:			  ;OUTPUT CHAR WITH NO SCROLL CHECK
	 PUSH  AX
	 PUSH  DX
	 JMP   CHROUT_A
CHROUT	 ENDP

;********************************************************************
;
;  SCROLL - SCROLL THE TEXT SCREEN
;
;	    INPUT:  NONE
;	    OUTPUT: NONE
;
;********************************************************************

SCROLL	 PROC
	 PUSH  AX
	 PUSH  BX
	 PUSH  DI
	 CMP   MSGLNS,12
	 JB    SCROLL_C
	 MOV   ROW,24
	 MOV   COL,1
	 MOV   MSGLNS,0
	 MOV   BX,OFFSET MSGMOR
SCROLL_Z:
	 MOV   AL,[BX]
	 INC   BX
	 CMP   AL,0
	 JE    SCROLL_Y
	 CALL  CHROUT_J
	 JMP   SHORT SCROLL_Z
SCROLL_Y:
	 MOV   SI,1
SCROLL_A:
	 CALL  CURSOR
	 SCANKEY
	 JZ    SCROLL_A
	 GETKEY
	 CMP   AL,13
	 JE    SCROLL_B
	 MOV   DI,1000
	 MOV   BX,30
	 CALL  SOUND
	 JMP   SHORT SCROLL_A
SCROLL_B:
	 CALL  CLR_LINE
SCROLL_C:
	 SCROLL_TXT
	 MOV   ROW,23
	 MOV   COL,1
	 POP   DI
	 POP   BX
	 POP   AX
	 RET
SCROLL	 ENDP

;********************************************************************
;
;  CLR_LINE - CLEAR THE CURRENT TEXT ROW
;
;	    INPUT:  NONE
;	    OUTPUT: NONE
;
;********************************************************************

CLR_LINE PROC
	 PUSH  AX
	 PUSH  BX
	 PUSH  CX
	 MOV   AL,ROW
	 SUB   AH,AH
	 SHR   AL,1
	 MUL   LIT160
	 ADD   AX,AX
	 ADD   AX,AX
	 MOV   BX,AX
	 MOV   AX,WHITE@W
	 MOV   CX,40*4
CLR_LINE_A:
	 MOV   GSCRN1@W [BX],AX
	 MOV   GSCRN2@W [BX],AX
	 INC   BX
	 INC   BX
	 LOOP  CLR_LINE_A
	 MOV   COL,1
	 POP   CX
	 POP   BX
	 POP   AX
	 RET
CLR_LINE ENDP

;********************************************************************
;
;  CLR_CHAR - CLEAR THE CURRENT TEXT CHARACTER
;
;	    INPUT:  NONE
;	    OUTPUT: NONE
;
;********************************************************************

CLR_CHAR PROC
	 PUSH  AX
	 PUSH  BX
	 PUSH  CX
	 CALL  CALC_CUR
	 MOV   AX,WHITE@W
	 MOV   CX,4
CLR_CHAR_A:
	 MOV   GSCRN1@W [BX],AX
	 MOV   GSCRN2@W [BX],AX
	 ADD   BX,80
	 LOOP  CLR_CHAR_A
	 POP   CX
	 POP   BX
	 POP   AX
	 RET
CLR_CHAR ENDP

;********************************************************************
;
;  GETLIN - GET INPUT LINE FROM KEYBOARD AND DISPLAY ON SCREEN
;
;	    INPUT:  NONE
;	    OUTPUT: "KEYBUF" CONTAINS THE LINE TYPED TERMINATED
;		    BY 00H
;
;********************************************************************

GETLIN	 PROC
	 PUSH  AX
	 PUSH  BX
	 PUSH  CX
	 PUSH  SI
	 MOV   SI,1
	 MOV   MSGLNS,0
	 MOV   BX,OFFSET KEYBUF
	 MOV   CH,MAXLINE
GETLIN_A:
	 CALL  CURSOR
	 SCANKEY
	 JZ    GETLIN_A
	 CALL  CLR_CHAR
	 GETKEY
	 CMP   AX,3B00H 	  ;F1 KEY?
	 JNE   GETLIN_AA
	 CALL  PANIC_SCR	  ;SET UP THE PANIC SCREEN
	 JMP   SHORT GETLIN_A	  ;RESUME GAME
GETLIN_AA:
	 CMP   AL,08H		  ;BACKSPACE?
	 JE    GETLIN_C 	  ;  YES
	 CMP   AL,0DH		  ;CARRIAGE RETURN?
	 JE    GETLIN_D 	  ;  YES
	 CMP   AL,' '             ;LESS THAN SPACE?
	 JB    GETLIN_A 	  ;  YES:IGNORE
	 CMP   AL,07AH		  ;GREATER THAN LOWER CASE "Z"?
	 JA    GETLIN_A 	  ;  YES:IGNORE
	 MOV   [BX],AL
	 INC   BX
	 CALL  CHROUT
	 DEC   CH
	 JNE   GETLIN_A
GETLIN_B:
	 CALL  CURSOR
	 SCANKEY
	 JZ    GETLIN_B
	 GETKEY
	 CMP   AL,0DH
	 JE    GETLIN_D
	 CMP   AL,08H
	 JE    GETLIN_C
	 PUSH  BX
	 MOV   DI,1000
	 MOV   BX,30
	 CALL  SOUND
	 POP   BX
	 JMP   SHORT GETLIN_B
GETLIN_C:
	 CMP   CH,MAXLINE	  ;AT START OF LINE?
	 JE    GETLIN_A 	  ;  YES:IGNORE
	 CALL  CHROUT
	 INC   CH
	 DEC   BX
	 JMP   SHORT GETLIN_A
GETLIN_D:
	 MOV   BYTE PTR [BX],0
	 CALL  CLR_CHAR
	 CALL  CHROUT
	 POP   SI
	 POP   CX
	 POP   BX
	 POP   AX
	 RET
GETLIN	 ENDP

;********************************************************************
;
;  CURSOR - BLINK CURSOR ON SCREEN
;
;	    INPUT:  SI = KEEPS CURSOR BLINK COUNT
;	    OUTPUT: NONE
;
;********************************************************************

CURSOR	 PROC
	 PUSH  AX
	 PUSH  BX
	 PUSH  CX
	 CMP   ROW,25
	 JB    CURSOR_A
	 CALL  SCROLL
CURSOR_A:
	 DEC   SI
	 JNZ   CURSOR_C
	 CALL  CALC_CUR
	 MOV   AL,CURCHR
	 XOR   AL,0FFH
	 MOV   CURCHR,AL
	 MOV   AH,AL
	 MOV   CX,4
CURSOR_B:
	 MOV   GSCRN1@W [BX],AX
	 MOV   GSCRN2@W [BX],AX
	 ADD   BX,80
	 LOOP  CURSOR_B
	 MOV   SI,800
CURSOR_C:
	 POP   CX
	 POP   BX
	 POP   AX
	 RET
CURSOR	 ENDP

;********************************************************************
;
;  CALC_CUR - CALCULATE SCREEN OFFSET FOR CURRENT ROW/COL
;
;	    INPUT:  NONE
;	    OUTPUT: BX = CURRENT SCREEN OFFSET
;
;********************************************************************

CALC_CUR PROC
	 PUSH  AX
	 MOV   AL,ROW
	 SUB   AH,AH
	 MUL   LIT160
	 ADD   AX,AX
	 ADD   AX,AX
	 SHR   AX,1
	 MOV   BL,COL
	 SHL   BL,1
	 SUB   BH,BH
	 ADD   BX,AX
	 POP   AX
	 RET
CALC_CUR ENDP

;********************************************************************
;
;  SOUND  - CREATE BEEP SOUND FOR "MORE" MESSAGE
;
;	    INPUT:  DI = FREQUENCY IN HERTZ (21 TO 65535)
;		    BX = DURATION IN HUNDREFTHS OF A SECOND
;	    OUTPUT: NONE
;
;********************************************************************

SOUND	 PROC
	 PUSH  AX
	 PUSH  BX
	 PUSH  CX
	 PUSH  DX
	 PUSH  DI
	 MOV   AL,0B6H		  ;WRITE TIMER MODE REGISTER
	 OUT   43H,AL
	 MOV   DX,14H		  ;TIMER DIVISOR =
	 MOV   AX,4F38H 	  ;	1331000/FREQUENCY
	 DIV   DI
	 OUT   42H,AL		  ;WRITE TIMER 2 COUNT LOW BYTE
	 MOV   AL,AH
	 OUT   42H,AL		  ;WRITE TIMER 2 COUNT HIGH BYTE
	 IN    AL,61H		  ;GET CURRENT PORT B SETTING
	 MOV   AH,AL		  ; AND SAVE IT IN "AH"
	 OR    AL,3		  ;TURN THE SPEAKER ON
	 OUT   61H,AL
SOUND_A:
	 MOV   CX,2801		  ;WAIT 10 MILLISECONDS
SOUND_B:
	 LOOP  SOUND_B
	 DEC   BX		  ;SPEAKER ON COUNT EXPIRED?
	 JNZ   SOUND_A		  ;  NO: KEEP SPEAKER ON
	 MOV   AL,AH		  ;OTHERWISE TURN SPEAKER OFF
	 OUT   61H,AL
	 POP   DI
	 POP   DX
	 POP   CX
	 POP   BX
	 POP   AX
	 RET
SOUND	 ENDP

;********************************************************************
;
;  SCRUP  - SCROLL SCREEN UP
;
;	    INPUT:  BX = SCREEN OFFSET FOR UPPER LEFT CORNER
;		    AL = # BYTES IN A SCROLL LINE
;		    AH = # LINES TO SCROLL
;	    OUTPUT: NONE
;
;********************************************************************

SCRUP	 PROC
	 PUSH  AX
	 PUSH  BX
	 PUSH  CX
	 PUSH  DX
	 PUSH  SI
	 MOV   SI,BX
	 MOV   DX,AX
	 DEC   DH
	 JZ    SCRUP_I
	 CALL  CALC_EOL 	  ;CALCULATE END OF LINE ADDR
	 MOV   CX,DX
SCRUP_A:
	 MOV   AX,GSCRN1@W [BX]
	 PUSH  AX
	 DEC   BX
	 DEC   BX
	 DEC   DL
	 JNZ   SCRUP_A
	 CMP   SI,2000H
	 JB    SCRUP_D
	 SUB   SI,2000H-80
SCRUP_B:
	 MOV   BX,SI
	 MOV   DL,CL
SCRUP_C:
	 MOV   AX,GSCRN1@W [BX]    ;MOVE EVEN SCAN LINE UP TO ODD
	 MOV   GSCRN2@W-80 [BX],AX
	 INC   BX
	 INC   BX
	 DEC   DL
	 JNZ   SCRUP_C
	 DEC   DH
	 JZ    SCRUP_F
SCRUP_D:
	 MOV   BX,SI
	 MOV   DL,CL
SCRUP_E:
	 MOV   AX,GSCRN2@W [BX]    ;MOVE ODD SCAN LINE UP TO EVEN
	 MOV   GSCRN1@W [BX],AX
	 INC   BX
	 INC   BX
	 DEC   DL
	 JNZ   SCRUP_E
	 ADD   SI,80
	 DEC   DH
	 JNZ   SCRUP_B
	 ADD   SI,2000H
SCRUP_F:
	 MOV   BX,SI
SCRUP_H:
	 POP   AX
	 MOV   GSCRN1@W [BX],AX
	 INC   BX
	 INC   BX
	 DEC   CL
	 JNZ   SCRUP_H
SCRUP_I:
	 POP   SI
	 POP   DX
	 POP   CX
	 POP   BX
	 POP   AX
	 RET
SCRUP	 ENDP

;********************************************************************
;
;  SCRDN  - SCROLL SCREEN DOWN
;
;	    INPUT:  BX = SCREEN OFFSET FOR UPPER LEFT CORNER
;		    AL = # BYTES IN A SCROLL LINE
;		    AH = # LINES TO SCROLL
;	    OUTPUT: NONE
;
;********************************************************************

SCRDN	 PROC
	 PUSH  AX
	 PUSH  BX
	 PUSH  CX
	 PUSH  DX
	 PUSH  SI
	 MOV   DX,AX		  ;SAVE SIZE PARAMETERS
	 DEC   DH		  ;# SCAN LINES - 1
	 JZ    SCRDN_G		  ;DONE IF ONLY 1 SCAN LINE
	 XCHG  AH,AL		  ;FLIP PARAMETERS
	 CALL  CALC_LAST	  ;CALC BOTTOM LEFT HAND CORNER
	 MOV   SI,BX		  ;SAVE SCREEN OFFSET
	 XCHG  AH,AL		  ;FLIP PARAMETERS
	 CALL  CALC_EOL 	  ;GET END OF CURR LINE ADDR
	 MOV   CL,DL		  ;GET LINE LENGTH
SCRDN_A:
	 MOV   AX,GSCRN1@W [BX]   ;SAVE BOTTOM SCAN LINE ON STACK
	 PUSH  AX
	 DEC   BX
	 DEC   BX
	 DEC   CL
	 JNZ   SCRDN_A
	 CMP   SI,2000H 	  ;IS BOTTOM LINE EVEN?
	 JB    SCRDN_D		  ;  YES:BEGIN SCROLL
	 SUB   SI,2000H 	  ;  NO:MAKE OFFSET ZERO RELATIVE
SCRDN_B:
	 MOV   BX,SI		  ;INIT SCROLL PARAMETERS
	 MOV   CL,DL
SCRDN_C:
	 MOV   AX,GSCRN1@W [BX]   ;MOVE EVEN SCAN LINE DOWN TO ODD
	 MOV   GSCRN2@W [BX],AX
	 INC   BX
	 INC   BX
	 DEC   CL
	 JNZ   SCRDN_C
	 DEC   DH		  ;DECREMENT # LINES TO SCROLL
	 JZ    SCRDN_F		  ;FILL IN TOP LINE FROM STACK
SCRDN_D:
	 MOV   CL,DL		  ;INIT SCROLL PARAMETERS
	 MOV   BX,SI
SCRDN_E:			  ;MOVE ODD SCAN LINE DOWN TO EVEN
	 MOV   AX,GSCRN2@W-80 [BX]
	 MOV   GSCRN1@W [BX],AX
	 INC   BX
	 INC   BX
	 DEC   CL
	 JNZ   SCRDN_E
	 SUB   SI,80		  ;DECREMENT TO NEXT SCAN LINE
	 DEC   DH		  ;DECREMENT # LINES TO SCROLL
	 JNZ   SCRDN_B		  ;CONTINUE IF MORE
	 ADD   SI,2000H 	  ;TOP LINE IS ODD SCAN LINE
SCRDN_F:
	 POP   AX		  ;FILL IN TOP LINE FROM STACK
	 MOV   GSCRN1@W [SI],AX
	 INC   SI
	 INC   SI
	 DEC   DL
	 JNZ   SCRDN_F
SCRDN_G:
	 POP   SI
	 POP   DX
	 POP   CX
	 POP   BX
	 POP   AX
	 RET
SCRDN	 ENDP

;********************************************************************
;
;  SCRLFT - SCROLL SCREEN LEFT
;
;	    INPUT:  BX = SCREEN OFFSET FOR UPPER LEFT CORNER
;		    AL = # BYTES IN A SCROLL LINE
;		    AH = # LINES TO SCROLL
;	    OUTPUT: NONE
;
;********************************************************************

SCRLFT	 PROC
	 PUSH  AX
	 PUSH  BX
	 PUSH  CX
	 PUSH  DX
	 PUSH  SI
	 PUSH  DI
	 MOV   SI,BX
	 MOV   DX,AX
	 MOV   DI,AX
	 MOV   CH,DH
SCRLFT_A:
	 MOV   AX,GSCRN1@W [BX]   ;SAVE LEFT COLUMN ON STACK
	 PUSH  AX
	 DEC   CH
	 JZ    SCRLFT_B
	 XOR   BX,2000H
	 CMP   BX,2000H
	 JAE   SCRLFT_A
	 ADD   BX,80
	 JMP   SHORT SCRLFT_A
SCRLFT_B:
	 DEC   DL		  ;DECREMENT LINE LENGTH
	 JZ    SCRLFT_F 	  ;IF ONLY ONE WORD TO SCROLL
SCRLFT_C:
	 MOV   BX,SI
	 MOV   CH,DH
	 PUSH  DX
SCRLFT_D:
	 MOV   AX,GSCRN1@W [BX]
	 MOV   DX,GSCRN1@W+2 [BX]
	 CALL  SHFT_LFT
	 MOV   GSCRN1@W [BX],AX
	 DEC   CH
	 JZ    SCRLFT_E
	 XOR   BX,2000H
	 CMP   BX,2000H
	 JAE   SCRLFT_D
	 ADD   BX,80
	 JMP   SHORT SCRLFT_D
SCRLFT_E:
	 POP   DX
	 INC   SI
	 INC   SI
	 DEC   DL
	 JNZ   SCRLFT_C
	 INC   BX
	 INC   BX
SCRLFT_F:
	 MOV   CX,DI
SCRLFT_G:
	 MOV   AX,GSCRN1@W [BX]
	 POP   DX
	 CALL  SHFT_LFT
	 MOV   GSCRN1@W [BX],AX
	 DEC   CH
	 JZ    SCRLFT_H
	 XOR   BX,2000H
	 CMP   BX,2000H
	 JB    SCRLFT_G
	 SUB   BX,80
	 JMP   SHORT SCRLFT_G
SCRLFT_H:
	 POP   DI
	 POP   SI
	 POP   DX
	 POP   CX
	 POP   BX
	 POP   AX
	 RET
SCRLFT	 ENDP

;	 SHIFT "DX" LEFT 2 PIXELS AND MOVE THEM INTO THE
;	 RIGHT SIDE OF "AX"

SHFT_LFT PROC
	 XCHG  AH,AL
	 XCHG  DH,DL
	 SHL   DX,1
	 RCL   AX,1
	 SHL   DX,1
	 RCL   AX,1
	 SHL   DX,1
	 RCL   AX,1
	 SHL   DX,1
	 RCL   AX,1
	 XCHG  AH,AL
	 XCHG  DH,DL
	 RET
SHFT_LFT ENDP

;********************************************************************
;
;  SCRRIT - SCROLL SCREEN RIGHT
;
;	    INPUT:  BX = SCREEN OFFSET FOR UPPER LEFT CORNER
;		    AL = # BYTES IN A SCROLL LINE
;		    AH = # LINES TO SCROLL
;	    OUTPUT: NONE
;
;********************************************************************

SCRRIT	 PROC
	 PUSH  AX
	 PUSH  BX
	 PUSH  CX
	 PUSH  DX
	 PUSH  SI
	 PUSH  DI
	 MOV   DX,AX
	 MOV   DI,AX
	 CALL  CALC_EOL
	 MOV   SI,BX
	 MOV   CH,DH
SCRRIT_A:
	 MOV   AX,GSCRN1@W [BX]   ;SAVE LEFT COLUMN ON STACK
	 PUSH  AX
	 DEC   CH
	 JZ    SCRRIT_B
	 XOR   BX,2000H
	 CMP   BX,2000H
	 JAE   SCRRIT_A
	 ADD   BX,80
	 JMP   SHORT SCRRIT_A
SCRRIT_B:
	 DEC   DL		  ;DECREMENT LINE LENGTH
	 JZ    SCRRIT_F 	  ;IF ONLY ONE WORD TO SCROLL
SCRRIT_C:
	 MOV   BX,SI
	 MOV   CH,DH
	 PUSH  DX
SCRRIT_D:
	 MOV   AX,GSCRN1@W [BX]
	 MOV   DX,GSCRN1@W-2 [BX]
	 CALL  SHFT_RIT
	 MOV   GSCRN1@W [BX],AX
	 DEC   CH
	 JZ    SCRRIT_E
	 XOR   BX,2000H
	 CMP   BX,2000H
	 JAE   SCRRIT_D
	 ADD   BX,80
	 JMP   SHORT SCRRIT_D
SCRRIT_E:
	 POP   DX
	 DEC   SI
	 DEC   SI
	 DEC   DL
	 JNZ   SCRRIT_C
	 DEC   BX
	 DEC   BX
SCRRIT_F:
	 MOV   CX,DI
SCRRIT_G:
	 MOV   AX,GSCRN1@W [BX]
	 POP   DX
	 CALL  SHFT_RIT
	 MOV   GSCRN1@W [BX],AX
	 DEC   CH
	 JZ    SCRRIT_H
	 XOR   BX,2000H
	 CMP   BX,2000H
	 JB    SCRRIT_G
	 SUB   BX,80
	 JMP   SHORT SCRRIT_G
SCRRIT_H:
	 POP   DI
	 POP   SI
	 POP   DX
	 POP   CX
	 POP   BX
	 POP   AX
	 RET
SCRRIT	 ENDP

;	 SHIFT "DX" RIGHT 2 PIXELS AND MOVE THEM INTO THE
;	 LEFT SIDE OF "AX"

SHFT_RIT PROC
	 XCHG  AH,AL
	 XCHG  DH,DL
	 SHR   DX,1
	 RCR   AX,1
	 SHR   DX,1
	 RCR   AX,1
	 SHR   DX,1
	 RCR   AX,1
	 SHR   DX,1
	 RCR   AX,1
	 XCHG  AH,AL
	 XCHG  DH,DL
	 RET
SHFT_RIT ENDP

;********************************************************************
;
;  REPCLR - REPLACE ONE COLOR WITH ANOTHER
;
;	    INPUT:  BX = SCREEN OFFSET FOR UPPER LEFT CORNER
;		    AL = # BYTES IN A SCROLL LINE
;		    AH = # LINES TO SCROLL
;	    OUTPUT: NONE
;
;********************************************************************

REPCLR	 PROC
	 PUSH  AX
	 PUSH  BX
	 PUSH  CX
	 PUSH  DX
	 PUSH  SI
	 MOV   DL,AL
	 MOV   CX,AX
	 MOV   SI,BX
	 CMP   SI,2000H
	 JB    REPCLR_A
	 SUB   SI,2000H
	 JMP   SHORT REPCLR_C
REPCLR_A:
	 MOV   CL,DL
	 MOV   BX,SI
REPCLR_B:
	 MOV   AX,GSCRN1@W [BX]   ;PROCESS EVEN SCAN LINES
	 CALL  CHGCLR
	 MOV   GSCRN1@W [BX],AX
	 INC   BX
	 INC   BX
	 DEC   CL
	 JNZ   REPCLR_B
	 DEC   CH
	 JZ    REPCLR_E
REPCLR_C:
	 MOV   CL,DL
	 MOV   BX,SI
REPCLR_D:
	 MOV   AX,GSCRN2@W [BX]   ;PROCESS ODD SCAN LINES
	 CALL  CHGCLR
	 MOV   GSCRN2@W [BX],AX
	 INC   BX
	 INC   BX
	 DEC   CL
	 JNZ   REPCLR_D
	 ADD   SI,80
	 DEC   CH
	 JNZ   REPCLR_A
REPCLR_E:
	 POP   SI
	 POP   DX
	 POP   CX
	 POP   BX
	 POP   AX
	 RET
REPCLR	 ENDP

;********************************************************************
;
;  CHGCLR - REPLACE ONE COLOR WITH ANOTHER
;
;	    INPUT:  AX = COLOR WORD FROM SCREEN
;	    OUTPUT: AX = MODIFIED COLOR WORD
;
;********************************************************************

CHGCLR	 PROC
	 PUSH  BX
	 PUSH  CX
	 PUSH  DX
	 MOV   CL,4
	 MOV   CH,4
	 MOV   DL,COLOR1
	 MOV   DH,COLOR2
CHGCLR_A:
	 ROL   AX,CL
	 MOV   BL,AL
	 AND   BL,03H
	 CMP   BL,DL
	 JNE   CHGCLR_B
	 MOV   BL,DH
	 AND   AL,0F0H
	 OR    AL,BL
	 SHL   BL,1
	 SHL   BL,1
	 OR    AL,BL
CHGCLR_B:
	 DEC   CH
	 JNZ   CHGCLR_A
	 POP   DX
	 POP   CX
	 POP   BX
	 RET
CHGCLR	 ENDP

;********************************************************************
;
;  FLPCLR - EXCHANGE TWO COLORS
;
;	    INPUT:  BX = SCREEN OFFSET FOR UPPER LEFT CORNER
;		    AL = # BYTES IN A SCROLL LINE
;		    AH = # LINES TO SCROLL
;	    OUTPUT: NONE
;
;********************************************************************

FLPCLR	 PROC
	 PUSH  AX
	 PUSH  BX
	 PUSH  CX
	 PUSH  DX
	 PUSH  SI
	 MOV   DL,AL
	 MOV   CX,AX
	 MOV   SI,BX
	 CMP   SI,2000H
	 JB    FLPCLR_A
	 SUB   SI,2000H
	 JMP   SHORT FLPCLR_C
FLPCLR_A:
	 MOV   CL,DL
	 MOV   BX,SI
FLPCLR_B:
	 MOV   AX,GSCRN1@W [BX]   ;PROCESS EVEN SCAN LINES
	 CALL  XCGCLR
	 MOV   GSCRN1@W [BX],AX
	 INC   BX
	 INC   BX
	 DEC   CL
	 JNZ   FLPCLR_B
	 DEC   CH
	 JZ    FLPCLR_E
FLPCLR_C:
	 MOV   CL,DL
	 MOV   BX,SI
FLPCLR_D:
	 MOV   AX,GSCRN2@W [BX]   ;PROCESS ODD SCAN LINES
	 CALL  XCGCLR
	 MOV   GSCRN2@W [BX],AX
	 INC   BX
	 INC   BX
	 DEC   CL
	 JNZ   FLPCLR_D
	 ADD   SI,80
	 DEC   CH
	 JNZ   FLPCLR_A
FLPCLR_E:
	 POP   SI
	 POP   DX
	 POP   CX
	 POP   BX
	 POP   AX
	 RET
FLPCLR	 ENDP

;********************************************************************
;
;  XCGCLR - EXCHANGE TWO COLORS
;
;	    INPUT:  AX = COLOR WORD FROM SCREEN
;	    OUTPUT: AX = MODIFIED COLOR WORD
;
;********************************************************************

XCGCLR	 PROC
	 PUSH  BX
	 PUSH  CX
	 PUSH  DX
	 MOV   CL,4
	 MOV   CH,4
	 MOV   DL,COLOR1
	 MOV   DH,COLOR2
XCGCLR_A:
	 ROL   AX,CL
	 MOV   BL,AL
	 AND   BL,03H
	 CMP   BL,DL
	 JNE   XCGCLR_B
	 MOV   BL,DH
	 JMP   SHORT XCGCLR_C
XCGCLR_B:
	 CMP   BL,DH
	 JNE   XCGCLR_D
	 MOV   BL,DL
XCGCLR_C:
	 AND   AL,0F0H
	 OR    AL,BL
	 SHL   BL,1
	 SHL   BL,1
	 OR    AL,BL
XCGCLR_D:
	 DEC   CH
	 JNZ   XCGCLR_A
	 POP   DX
	 POP   CX
	 POP   BX
	 RET
XCGCLR	 ENDP

;********************************************************************
;
;  CALC_EOL - CALC END OF LINE ADDR FOR CURRENT OVERLAY
;
;	    INPUT:  AL = LINE LENGTH OF OVERLAY (# WORDS)
;		    BX = POINTER TO LEFT CORNER OF OVERLAY
;	    OUTPUT: BX = POINTER TO RIGHT CORNER OF OVERLAY
;
;********************************************************************

CALC_EOL PROC
	 PUSH  AX
	 SUB   AH,AH
	 SHL   AX,1		  ;LINE LENGTH * 2
	 SUB   AX,2		  ;LINE LENGTH * 2 - 2
	 ADD   BX,AX		  ;CALC EOL POINTER
	 POP   AX
	 RET
CALC_EOL ENDP

;********************************************************************
;
;  CALC_LAST - CALC END OF LINE ADDR FOR CURRENT OVERLAY
;
;	    INPUT:  AL = # OF SCAN LINES IN OVERLAY
;		    BX = POINTER TO TOP SCAN LINE OF OVERLAY
;	    OUTPUT: BX = POINTER TO BOTTOM SCAN LINE OF OVERLAY
;
;********************************************************************

CALC_LAST PROC
	 PUSH  AX
	 PUSH  CX
	 MOV   CL,AL		  ;SAVE # OF SCAN LINES
	 SHR   AL,1		  ;# OF SCAN LINES / 2
	 MUL   EIGHTY		  ;# OF SCAN LINES / 2 * MAX LINE LEN
	 ADD   BX,AX		  ;CALC NEW SCAN LINE OFFSET
	 CMP   BX,2000H 	  ;IS TOP LINE EVEN?
	 JB    CALC_LAST_A	  ;  YES
	 TEST  CL,1		  ;ODD NUMBER OF SCAN LINES?
	 JNZ   CALC_LAST_B	  ;  NO:BOTTOM SCAN LINE IS ODD
	 SUB   BX,2000H-80	  ;  YES:BUMP TO NEXT LINE
	 JMP   SHORT CALC_LAST_B  ;ALL DONE
CALC_LAST_A:
	 TEST  CL,1		  ;ODD NUMBER OF SCAN LINES?
	 JNZ   CALC_LAST_B	  ;  NO:END ON EVEN SCAN LINE
	 ADD   BX,2000H 	  ;  YES:END ON ODD SCAN LINE
CALC_LAST_B:
	 POP   CX
	 POP   AX
	 RET
CALC_LAST ENDP

;********************************************************************
;
;  LODGAM - LOAD SAVED GAME ROUTINE
;
;	    INPUT:  NONE
;	    OUTPUT: NONE
;
;********************************************************************

LODGAM	 PROC
	 CALL  GETPOS
	 CMP   AL,13
	 JE    LODGAM_Z
	 DISABLE
	 F$SETDTA
	 F$OPEN GAMSAV
	 JNZ	LODGAM_B
	 MOV	AX,DS
	 MOV	ES,AX
	 F$READ GAMSAV
	 JNE	LODGAM_C
	 CMP	DTABUF,ADVMARK
	 JNE	LODGAM_D
	 MOV	AL,ADVNUM
	 CMP	AL,DTABUF+1
	 JNE	LODGAM_D
	 MOV	SI,OFFSET DTABUF
	 MOV	DI,OFFSET STARTVAR
	 MOV	CX,128
	 REP	MOVSB
	 MOV	BX,RMTB_LEN
	 MOV	CL,7
	 SHR	BX,CL
	 INC	BX
	 MOV	DI,OFFSET ROOMTB
LODGAM_A:
	 F$READ GAMSAV
	 JNE	LODGAM_C
	 MOV	SI,OFFSET DTABUF
	 MOV	CX,128
	 REP	MOVSB
	 DEC	BX
	 JNZ	LODGAM_A
	 JMP   SAVGAM_B
LODGAM_Z:
	 RET
LODGAM_B:
	 MOV   BX,OFFSET SAVMSG4
	 PUSH  BX
	 JMP   SHORT LODGAM_F
LODGAM_C:
	 MOV   BX,OFFSET SAVMSG5
	 JMP   SHORT LODGAM_E
LODGAM_D:
	 MOV   BX,OFFSET SAVMSG6
LODGAM_E:
	 PUSH  BX
	 F$CLOSE GAMSAV
LODGAM_F:
	 POP   BX
	 MOV   AX,VIDEO
	 MOV   ES,AX
	 CALL  DISPLY
	 ENABLE
	 JMP   REPLY
LODGAM	 ENDP

;********************************************************************
;
;  SAVGAM - SAVE GAME ROUTINE
;
;	    INPUT:  NONE
;	    OUTPUT: NONE
;
;********************************************************************

SAVGAM	 PROC
	 CALL  GETPOS
	 CMP   AL,13		  ;ABORTED?
	 JE    SAVGAM_Z 	  ;  YES
	 DISABLE
	 F$SETDTA
	 F$CREATE GAMSAV
	 JNZ   SAVGAM_C
	 MOV   AX,DS
	 MOV   ES,AX
	 MOV   SAVEKEY1,ADVMARK
	 MOV   AL,ADVNUM
	 MOV   SAVEKEY2,AL
	 MOV   SI,OFFSET STARTVAR
	 MOV   DI,OFFSET DTABUF
	 MOV   CX,128
	 REP   MOVSB
	 F$WRITE GAMSAV
	 JNZ   SAVGAM_D
	 MOV   BX,RMTB_LEN
	 MOV   CL,7
	 SHR   BX,CL		  ;LEN OF ROOM TBL / 128
	 INC   BX
	 MOV   SI,OFFSET ROOMTB
SAVGAM_A:
	 MOV   DI,OFFSET DTABUF
	 MOV   CX,128
	 REP   MOVSB
	 F$WRITE GAMSAV
	 JNZ   SAVGAM_D
	 DEC   BX
	 JNZ   SAVGAM_A
SAVGAM_B:
	 F$CLOSE GAMSAV
	 MOV   AX,VIDEO
	 MOV   ES,AX
	 ENABLE
SAVGAM_Z:
	 RET
SAVGAM_C:
	 MOV   BX,OFFSET SAVMSG2
	 JMP   SHORT SAVGAM_E
SAVGAM_D:
	 MOV   BX,OFFSET SAVMSG3
SAVGAM_E:
	 CALL  DISPLY
	 JMP   SHORT SAVGAM_B
SAVGAM	 ENDP

;********************************************************************
;
;  GETPOS - GET SAVE/LOAD GAME POSITION
;
;	    INPUT:  NONE
;	    OUTPUT: AL = SAVE POSITION (13H = ABORT)
;
;********************************************************************

GETPOS	 PROC
	 MOV   BX,OFFSET SAVMSG1
	 CALL  DISPLY
	 MOV   SI,1
GETPOS_A:
	 CALL  CURSOR
	 SCANKEY
	 JZ    GETPOS_A
	 GETKEY
	 CMP   AL,13
	 JE    GETPOS_B
	 CMP   AL,'0'
	 JB    GETPOS_C
	 CMP   AL,'9'
	 JA    GETPOS_C
	 MOV   SAVNO,AL
	 CALL  CLR_CHAR
	 CALL  CHROUT
	 MOV   AL,13
	 CALL  CHROUT
	 MOV   AL,SAVNO
	 RET
GETPOS_B:
	 CALL  CLR_CHAR
	 CALL  CHROUT
	 RET
GETPOS_C:
	 MOV   DI,1000
	 MOV   BX,30
	 CALL  SOUND
	 JMP   SHORT GETPOS_A
GETPOS	 ENDP

;********************************************************************
;
;  DSKERR - CRITICAL DISK I/O ERROR ROUTINE
;
;	    INPUT:  NONE
;	    OUTPUT: NONE
;
;********************************************************************

DSKERR	 PROC
	 POP   AX		  ;REMOVE DOS REGS
	 POP   AX
	 POP   AX
	 POP   AX		  ;RESTORE MY REGS
	 POP   BX
	 POP   CX
	 POP   DX
	 POP   SI
	 POP   DI
	 POP   BP
	 POP   DS
	 POP   ES
	 STI
	 MOV   BX,OFFSET SAVERR
	 CALL  DISPLY
	 ENABLE
	 JMP   REPLY
DSKERR	 ENDP

;********************************************************************
;
;  CHKANT - TIMER TICK INTERRUPT ROUTINE TO DRIVE ANTIMATION
;
;	    INPUT:  NONE
;	    OUTPUT: NONE
;
;********************************************************************

ChkAntInProc db     0

CHKANT	 PROC
	 cmp   ChkAntInProc,0
	 pushf
	 call  OldInt08
	 jne   chkant_d
	 mov   ChkAntInProc,1
	 PUSH  AX
	 PUSH  BX
	 PUSH  CX
	 PUSH  DX
	 PUSH  SI
	 PUSH  DI
	 PUSH  DS
	 MOV   DS,DS_SAVE
	 MOV   AL,RANDOM
	 SUB   CX,CX
	 MOV   DS,CX
	 ASSUME DS:ABS0
	 ADD   AL,DS:TIMER_LOW2
	 XOR   AL,DS:TIMER_LOW1
	 INC   AL
	 MOV   DS,DS_SAVE
	 ASSUME DS:DATA
	 MOV   RANDOM,AL
	 TEST  ANTIMSW,0FFH
	 JZ    CHKANT_C
	 MOV   BX,OFFSET ANTTAB
	 MOV   AL,ROOM
CHKANT_A:
	 TEST  BYTE PTR [BX],0FFH
	 JE    CHKANT_C
	 CMP   AL,[BX]
	 JE    CHKANT_B
	 ADD   BX,3
	 JMP   SHORT CHKANT_A
CHKANT_B:
	 DISABLE
	 CALL  WORD PTR [BX+1]
	 ENABLE
CHKANT_C:
	 POP   DS
	 POP   DI
	 POP   SI
	 POP   DX
	 POP   CX
	 POP   BX
	 POP   AX
chkant_d:
	 mov   ChkAntInProc,0
	 IRET
CHKANT	 ENDP

PANIC_SCR PROC
	 DISABLE
	 PUSH  AX
	 PUSH  BX
	 PUSH  CX
	 PUSH  DX
	 PUSH  SI
	 PUSH  DI
	 PUSH  DS
	 PUSH  ES
	 PUSH  ES
	 MOV   AX,DS
	 MOV   ES,AX
	 POP   DS
	 MOV   SI,0
	 MOV   DI,OFFSET SAVE_SCR
	 MOV   CX,(END_SCR - SAVE_SCR)
	 REP   MOVSB
	 MOV   AL,3
	 MOV   AH,0
	 INT   10H
	 MOV   AX,ES
	 MOV   DS,AX
	 MOV   DX,OFFSET DOS_PROMPT
	 MOV   AH,9
	 INT   21H
PANIC_SCR_A:
	 GETKEY
	 CMP   AX,3C00H 	       ;F2 KEY
	 JNE   PANIC_SCR_A
	 POP   ES
	 POP   DS
	 INIT_VIDEO
	 MOV   SI,OFFSET SAVE_SCR
	 MOV   DI,0
	 MOV   CX,(END_SCR - SAVE_SCR)
	 REP   MOVSB
	 POP   DI
	 POP   SI
	 POP   DX
	 POP   CX
	 POP   BX
	 POP   AX
	 RET
PANIC_SCR ENDP

CODE	 ENDS
	 END

;	 END FILE = ADVSYSI/ASM
